使用RestTemplate上传文件

您所在的位置:网站首页 resttemplate 发送文件流 使用RestTemplate上传文件

使用RestTemplate上传文件

2024-07-09 03:46:48| 来源: 网络整理| 查看: 265

最近在开发中使用到RestTemplate来处理服务间的请求,服务提供的接口需要传入一个文件作为参数解析,而RestTemplate发起的post请求都是将参数放入键值对中并包装到请求体,对于文件的传递该怎么处理呢?

1. RestTemplate的消息转换器

RestTemplate作为restful接口调用的模板类,通过设置的消息转换器类将请求或返回结果转换成需要的类型。使用RestTemplate调用服务传递文件要使用ResourceHttpMessageConverter转换器。

1.1 文件接收服务接口定义

首先来看一下上传文件是如何与ResourceHttpMessageConverter产生关系的,如下所示为一个常见的文件上传服务接口定义。

 @RestController  @RequestMapping("/file")  public class FileController {      @RequestMapping("/upload")      public String upload(MultipartFile file, String id){          String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));          String name = file.getOriginalFilename();          long size = file.getSize();          String type = file.getContentType();  ​          String result = "时间:" + time + ",文件名称:" + name + "文件大小:" + size + ",文件类型:" + type + ",id传入值:" + id;          return result;     }  } 复制代码

Java对应的Web服务中,上传的文件对象通常是使用MultipartFile对象来接收,该对象继承了org.springframework.core.io包中的InputStreamSource接口,这是Spring核心工具包的输入流接口。

1.2 资源请求消息转换器

ResourceHttpMessageConverter转换器作为RestTemplate中基本的转换器类型,继承了抽象类转换器AbstractHttpMessageConverter,并通过泛型指定了转换类型为Resource,进入到Resource中可以发现,同样实现了InputStreamSource接口。

//转换器实现 public class ResourceHttpMessageConverter extends AbstractHttpMessageConverter { ... } 复制代码

ResourceHttpMessageConverter转换器可以对Resource类型进行处理,而Resource作为Java中的接口,其下的实现类常用的有FileSystemResource、ByteArrayRestream、InputStreamResource。

2. RestTemplate实现上传文件

既然RestTemplate中提供了对文件资源的转换器类型,接下来就看一下如何使用对应的字节流对象进行文件参数的传递。

2.1 FileSystemResource

FileSystemResource作为资源访问类,从名称即可看出是从文件系统中获取资源,通常是根据文件路径或File对象来创建。

根据FileSystemResource的特点,可以使用其读取指定路径下的文件,并将文件作为参数请求到服务中。

//读取本地文件上传 @RequestMapping("/remotRequest") public String remotRequest(){ RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/excel/upload"; MultiValueMap parts = new LinkedMultiValueMap(); //读取本地文件 "D:/upload/file"; String filePath = "D:/upload/file/test.xlsx"; FileSystemResource fileSystemResource = new FileSystemResource(filePath); MultiValueMap params = new LinkedMultiValueMap(); HttpHeaders headers = new HttpHeaders(); params.add("file",fileSystemResource); headers.setContentType(MediaType.MULTIPART_FORM_DATA); HttpEntity requestEntity = new HttpEntity(params, headers); String result = restTemplate.postForObject(url,requestEntity ,String.class); return result; } 复制代码

尽管使用FileSystemResource读取了本地文件进行上传请求,如果文件信息也是从当前服务接口中获取得到,又怎么处理呢?

由于FileSystemResource是操作文件系统资源的,直接用来传递参数不可行,但是可以使用中转的办法,先将接口获取到的文件暂存至临时路径,然后从临时路径中获取文件实现远程传参,并在传参结束后删除文件。

 @RequestMapping("/upload")  public String upload(MultipartFile file, String id) throws IOException {   //定义并创建临时文件目录      String tempPath = "D:/file/temp/";      boolean makeSuccess = new File(tempPath).mkdir();      //目录下创建同名文件路径      File tempFile = new File(tempPath + file.getOriginalFilename());      if(tempFile.exists()){          tempFile.delete();     }      if(!tempFile.exists()){          //直接复制文件到指定路径          file.transferTo(tempFile);     }      //此时可以用FileSystemResource读取文件了      FileSystemResource fileSystemResource = new FileSystemResource(tempFile);            //之后可以使用相同方式完成文件传入请求     ...            //文件使用结束后删除临时存储的文件      tempFile.delete();  } 复制代码

如果说这种使用方式太繁琐,需要临时存储再读取,忘记删除时会永久占用磁盘空间,那就可以使用ByteArrayResource和InputStreamResource的方式来传递文件。

2.2 ByteArrayResource

ByteArrayResource在从给定的字节数组中加载内容时非常好用,而不用一味的使用InputStreamResource进行处理。对于将本地内容创建为邮件附件时使用ByteArrayResource是一个好的选择,因为JavaMail需要能够多次读取流数据。

在使用ByteArrayResource对象创建资源对象时,需要重写定义的getFilename()和contentLength()两个方法,返回文件的名称和大小信息,否则在文件流传递时无法获取到有效的文件资源而导致最终服务接收文件异常。

@RequestMapping("/upload") public String upload(MultipartFile file, String id) throws IOException { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/excel/upload"; MultiValueMap params = new LinkedMultiValueMap(); ByteArrayResource fileAsResource = new ByteArrayResource(file.getBytes()) { @Override public String getFilename() { return file.getOriginalFilename(); } @Override public long contentLength() { return file.getSize(); } }; params.add("file", fileAsResource); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); HttpEntity requestEntity = new HttpEntity(params, headers); String result = restTemplate.postForObject(url,requestEntity ,String.class); return result; } 复制代码 2.3 InputStreamResource

教程

Spring官方文档介绍,仅当没有其他特定的资源实现适用时才应使用,在可能的情况下更推荐使用 ByteArrayResource或任何基于文件的Resource实现。

InputStreamResource是Spring中标准的输入流资源对象,读取常见的字节数据,使用InputStreamResource对象将接收的文件内容转成字节流的方式和ByteArrayResource类似,也需要覆写对应的getFilename()和contentLength()方法,以此来存放文件的名称和大小信息。

@RequestMapping("/upload") public String upload(MultipartFile file, String id) throws IOException { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/excel/upload"; MultiValueMap params = new LinkedMultiValueMap(); InputStreamResource inputStreamResource = new InputStreamResource(file.getInputStream()){ @Override public String getFilename() { return file.getOriginalFilename(); } @Override public long contentLength() { return file.getSize(); } }; params.add("file", inputStreamResource); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); HttpEntity requestEntity = new HttpEntity(params, headers); String result = restTemplate.postForObject(url,requestEntity ,String.class); return result; } 复制代码 3. 总结

RestTemplate的ResourceHttpMessageConverter消息转换器定义了文件资源的处理,允许RestTemplate将文件作为参数传递,在实际上传文件时要根据实际需要选择不同的资源形式,需要注意的有:

如果处理本地资源发起请求,则优先使用FileSystemResource,对于非本地资源也可以使用暂存的方式实现请求操作对于需要多次读取的文件资源,考虑使用ByteArrayResource存放文件字节信息,并实现文件传递的请求InputStreamResource是更普遍的资源处理方式,如果其他方式不再适合,就使用InputStreamResource吧

使用InputStreamResource必须覆写两个方法 contentLength 和 getFileName。

作者:东方甲乙木土 链接:https://juejin.cn/post/7036365306574405640 来源:稀土掘金  

通过`RestTemplate`上传文件(InputStreamResource详解) - 爬行 - 博客园

不加任何文件流处理方法会报错:

Required request part ‘file‘ is not present

 原因是 formdata 里面缺失 filename 属性,

所以必须添加文件流的处理方式,重写 getFilename()和contentLength()两个方法

 



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭